// Go作者版权所有。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

// go:构建忽略
// +构建忽略

package main

import "strings"

// 笔记：
// -整数类型位于寄存器的低位。上部是垃圾。
// -布尔类型使用寄存器的低位字节。0=假，1=真。
// 上面的字节是垃圾。
// -*常量指令可能使用大于指令编码的常量。
// 在这种情况下，汇编程序扩展到多条指令并使用tmp
// 寄存器（R27）。

// 后缀对各种指令的位宽度进行编码。
// D（双字）=64位
// W（字）=32位
// H（半字）=16位
// HU=16位无符号
// B（字节）=8位
// BU=8位无符号
// S（单）=32位浮点
// D（双）=64位浮点

// 注：regalloc中未使用的寄存器不包括在此列表中，
// 所以regmask保持在int64内
// 手工编码时要小心。
var regNamesARM64 = []string{
	"R0",
	"R1",
	"R2",
	"R3",
	"R4",
	"R5",
	"R6",
	"R7",
	"R8",
	"R9",
	"R10",
	"R11",
	"R12",
	"R13",
	"R14",
	"R15",
	"R16",
	"R17",
	"R18", // 平台寄存器，未使用
	"R19",
	"R20",
	"R21",
	"R22",
	"R23",
	"R24",
	"R25",
	"R26",
	// R27=regalloc中未使用REGTMP
	"g",   // 又名R28
	"R29", // 帧指针，未使用
	"R30", // 又名REGLINK
	"SP",  // 又名R31

	"F0",
	"F1",
	"F2",
	"F3",
	"F4",
	"F5",
	"F6",
	"F7",
	"F8",
	"F9",
	"F10",
	"F11",
	"F12",
	"F13",
	"F14",
	"F15",
	"F16",
	"F17",
	"F18",
	"F19",
	"F20",
	"F21",
	"F22",
	"F23",
	"F24",
	"F25",
	"F26",
	"F27",
	"F28",
	"F29",
	"F30",
	"F31",

	// 如果添加寄存器，请在运行时更新asyncPreempt。

	// 伪寄存器
	"SB",
}

func init() {
	// 将reg名称映射到reg整数。
	if len(regNamesARM64) > 64 {
		panic("too many registers")
	}
	num := map[string]int{}
	for i, name := range regNamesARM64 {
		num[name] = i
	}
	buildReg := func(s string) regMask {
		m := regMask(0)
		for _, r := range strings.Split(s, " ") {
			if n, ok := num[r]; ok {
				m |= regMask(1) << uint(n)
				continue
			}
			panic("register " + r + " not found")
		}
		return m
	}

	// 通用单个寄存器掩码
	var (
		gp         = buildReg("R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30")
		gpg        = gp | buildReg("g")
		gpsp       = gp | buildReg("SP")
		gpspg      = gpg | buildReg("SP")
		gpspsbg    = gpspg | buildReg("SB")
		fp         = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31")
		callerSave = gp | fp | buildReg("g") // runtime.setg（以及任何调用它的东西）可能会重击g
		r0         = buildReg("R0")
		r1         = buildReg("R1")
		r2         = buildReg("R2")
		r3         = buildReg("R3")
	)
	// 公共区域信息
	var (
		gp01           = regInfo{inputs: nil, outputs: []regMask{gp}}
		gp0flags1      = regInfo{inputs: []regMask{0}, outputs: []regMask{gp}}
		gp11           = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
		gp11sp         = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
		gp1flags       = regInfo{inputs: []regMask{gpg}}
		gp1flags1      = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
		gp11flags      = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp, 0}}
		gp21           = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}}
		gp21nog        = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}}
		gp21flags      = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp, 0}}
		gp2flags       = regInfo{inputs: []regMask{gpg, gpg}}
		gp2flags1      = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}}
		gp2flags1flags = regInfo{inputs: []regMask{gp, gp, 0}, outputs: []regMask{gp, 0}}
		gp2load        = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
		gp22           = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp, gp}}
		gp31           = regInfo{inputs: []regMask{gpg, gpg, gpg}, outputs: []regMask{gp}}
		gpload         = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
		gpstore        = regInfo{inputs: []regMask{gpspsbg, gpg}}
		gpstore0       = regInfo{inputs: []regMask{gpspsbg}}
		gpstore2       = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}}
		gpxchg         = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
		gpcas          = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}, outputs: []regMask{gp}}
		fp01           = regInfo{inputs: nil, outputs: []regMask{fp}}
		fp11           = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
		fpgp           = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}
		gpfp           = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}}
		fp21           = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
		fp31           = regInfo{inputs: []regMask{fp, fp, fp}, outputs: []regMask{fp}}
		fp2flags       = regInfo{inputs: []regMask{fp, fp}}
		fp1flags       = regInfo{inputs: []regMask{fp}}
		fpload         = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{fp}}
		fp2load        = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{fp}}
		fpstore        = regInfo{inputs: []regMask{gpspsbg, fp}}
		fpstore2       = regInfo{inputs: []regMask{gpspsbg, gpg, fp}}
		readflags      = regInfo{inputs: nil, outputs: []regMask{gp}}
	)
	ops := []opData{
		// 二进制操作
		{name: "ADCSflags", argLength: 3, reg: gp2flags1flags, typ: "(UInt64,Flags)", asm: "ADCS", commutative: true}, // arg0+arg1+进位，设置标志。
		{name: "ADCzerocarry", argLength: 1, reg: gp0flags1, typ: "UInt64", asm: "ADC"},                               // ZR+ZR+进位
		{name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true},                                         // arg0+arg1
		{name: "ADDconst", argLength: 1, reg: gp11sp, asm: "ADD", aux: "Int64"},                                       // arg0+生长素
		{name: "ADDSconstflags", argLength: 1, reg: gp11flags, typ: "(UInt64,Flags)", asm: "ADDS", aux: "Int64"},      // arg0+生长素，设置标志。
		{name: "ADDSflags", argLength: 2, reg: gp21flags, typ: "(UInt64,Flags)", asm: "ADDS", commutative: true},      // arg0+arg1，设置标志。
		{name: "SUB", argLength: 2, reg: gp21, asm: "SUB"},                                                            // arg0-arg1
		{name: "SUBconst", argLength: 1, reg: gp11, asm: "SUB", aux: "Int64"},                                         // arg0-生长素
		{name: "SBCSflags", argLength: 3, reg: gp2flags1flags, typ: "(UInt64,Flags)", asm: "SBCS"},                    // arg0-（arg1+借用），设置标志。
		{name: "SUBSflags", argLength: 2, reg: gp21flags, typ: "(UInt64,Flags)", asm: "SUBS"},                         // arg0-arg1，设置标志。
		{name: "MUL", argLength: 2, reg: gp21, asm: "MUL", commutative: true},                                         // arg0*arg1
		{name: "MULW", argLength: 2, reg: gp21, asm: "MULW", commutative: true},                                       // arg0*arg1，32位
		{name: "MNEG", argLength: 2, reg: gp21, asm: "MNEG", commutative: true},                                       // -arg0*arg1
		{name: "MNEGW", argLength: 2, reg: gp21, asm: "MNEGW", commutative: true},                                     // -arg0*arg1，32位
		{name: "MULH", argLength: 2, reg: gp21, asm: "SMULH", commutative: true},                                      // （arg0*arg1）>>64，已签名
		{name: "UMULH", argLength: 2, reg: gp21, asm: "UMULH", commutative: true},                                     // （arg0*arg1）>>64，未签名
		{name: "MULL", argLength: 2, reg: gp21, asm: "SMULL", commutative: true},                                      // arg0*arg1，有符号，32位mult结果为64位
		{name: "UMULL", argLength: 2, reg: gp21, asm: "UMULL", commutative: true},                                     // arg0*arg1，无符号，32位mult结果为64位
		{name: "DIV", argLength: 2, reg: gp21, asm: "SDIV"},                                                           // arg0/arg1，已签名
		{name: "UDIV", argLength: 2, reg: gp21, asm: "UDIV"},                                                          // arg0/arg1，未升级
		{name: "DIVW", argLength: 2, reg: gp21, asm: "SDIVW"},                                                         // arg0/arg1，有符号，32位
		{name: "UDIVW", argLength: 2, reg: gp21, asm: "UDIVW"},                                                        // arg0/arg1，非屏蔽，32位
		{name: "MOD", argLength: 2, reg: gp21, asm: "REM"},                                                            // arg0%arg1，已签名
		{name: "UMOD", argLength: 2, reg: gp21, asm: "UREM"},                                                          // arg0%arg1，未签名
		{name: "MODW", argLength: 2, reg: gp21, asm: "REMW"},                                                          // arg0%arg1，有符号，32位
		{name: "UMODW", argLength: 2, reg: gp21, asm: "UREMW"},                                                        // arg0%arg1，无符号，32位

		{name: "FADDS", argLength: 2, reg: fp21, asm: "FADDS", commutative: true},   // arg0+arg1
		{name: "FADDD", argLength: 2, reg: fp21, asm: "FADDD", commutative: true},   // arg0+arg1
		{name: "FSUBS", argLength: 2, reg: fp21, asm: "FSUBS"},                      // arg0-arg1
		{name: "FSUBD", argLength: 2, reg: fp21, asm: "FSUBD"},                      // arg0-arg1
		{name: "FMULS", argLength: 2, reg: fp21, asm: "FMULS", commutative: true},   // arg0*arg1
		{name: "FMULD", argLength: 2, reg: fp21, asm: "FMULD", commutative: true},   // arg0*arg1
		{name: "FNMULS", argLength: 2, reg: fp21, asm: "FNMULS", commutative: true}, // -（arg0*arg1）
		{name: "FNMULD", argLength: 2, reg: fp21, asm: "FNMULD", commutative: true}, // -（arg0*arg1）
		{name: "FDIVS", argLength: 2, reg: fp21, asm: "FDIVS"},                      // arg0/arg1
		{name: "FDIVD", argLength: 2, reg: fp21, asm: "FDIVD"},                      // arg0/arg1

		{name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0和arg1
		{name: "ANDconst", argLength: 1, reg: gp11, asm: "AND", aux: "Int64"}, // arg0&生长素
		{name: "OR", argLength: 2, reg: gp21, asm: "ORR", commutative: true},  // arg0 | arg1
		{name: "ORconst", argLength: 1, reg: gp11, asm: "ORR", aux: "Int64"},  // arg0 |生长素
		{name: "XOR", argLength: 2, reg: gp21, asm: "EOR", commutative: true}, // arg0^arg1
		{name: "XORconst", argLength: 1, reg: gp11, asm: "EOR", aux: "Int64"}, // arg0^生长素
		{name: "BIC", argLength: 2, reg: gp21, asm: "BIC"},                    // arg0和^arg1
		{name: "EON", argLength: 2, reg: gp21, asm: "EON"},                    // arg0^^arg1
		{name: "ORN", argLength: 2, reg: gp21, asm: "ORN"},                    // arg0 | ^arg1

		{name: "LoweredMuluhilo", argLength: 2, reg: gp22, resultNotInArgs: true}, // arg0*arg1，返回值（高，低）

		// 一元操作
		{name: "MVN", argLength: 1, reg: gp11, asm: "MVN"},                                    // ^arg0
		{name: "NEG", argLength: 1, reg: gp11, asm: "NEG"},                                    // -arg0
		{name: "NEGSflags", argLength: 1, reg: gp11flags, typ: "(UInt64,Flags)", asm: "NEGS"}, // -arg0，设置标志。
		{name: "NGCzerocarry", argLength: 1, reg: gp0flags1, typ: "UInt64", asm: "NGC"},       // -如果借用，则为1，否则为0。
		{name: "FABSD", argLength: 1, reg: fp11, asm: "FABSD"},                                // abs（arg0），浮动64
		{name: "FNEGS", argLength: 1, reg: fp11, asm: "FNEGS"},                                // -arg0，32
		{name: "FNEGD", argLength: 1, reg: fp11, asm: "FNEGD"},                                // -arg0，64
		{name: "FSQRTD", argLength: 1, reg: fp11, asm: "FSQRTD"},                              // sqrt（arg0），浮点64
		{name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS"},                              // sqrt（arg0），浮动32
		{name: "REV", argLength: 1, reg: gp11, asm: "REV"},                                    // 字节反转，64位
		{name: "REVW", argLength: 1, reg: gp11, asm: "REVW"},                                  // 字节反转，32位
		{name: "REV16", argLength: 1, reg: gp11, asm: "REV16"},                                // 每个16位半字中的字节反转，64位
		{name: "REV16W", argLength: 1, reg: gp11, asm: "REV16W"},                              // 每个16位半字中的字节反转，32位
		{name: "RBIT", argLength: 1, reg: gp11, asm: "RBIT"},                                  // 位反转，64位
		{name: "RBITW", argLength: 1, reg: gp11, asm: "RBITW"},                                // 位反转，32位
		{name: "CLZ", argLength: 1, reg: gp11, asm: "CLZ"},                                    // 前导零计数，64位
		{name: "CLZW", argLength: 1, reg: gp11, asm: "CLZW"},                                  // 计数前导零，32位
		{name: "VCNT", argLength: 1, reg: fp11, asm: "VCNT"},                                  // 对每个8位单元的设置位进行计数，并将结果存储在每个8位单元中
		{name: "VUADDLV", argLength: 1, reg: fp11, asm: "VUADDLV"},                            // 64位值中八个字节的无符号和，零扩展到64位。
		{name: "LoweredRound32F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},
		{name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},

		// 3操作数，加数在前
		{name: "FMADDS", argLength: 3, reg: fp31, asm: "FMADDS"},   // +arg0+（arg1*arg2）
		{name: "FMADDD", argLength: 3, reg: fp31, asm: "FMADDD"},   // +arg0+（arg1*arg2）
		{name: "FNMADDS", argLength: 3, reg: fp31, asm: "FNMADDS"}, // -arg0-（arg1*arg2）
		{name: "FNMADDD", argLength: 3, reg: fp31, asm: "FNMADDD"}, // -arg0-（arg1*arg2）
		{name: "FMSUBS", argLength: 3, reg: fp31, asm: "FMSUBS"},   // +arg0-（arg1*arg2）
		{name: "FMSUBD", argLength: 3, reg: fp31, asm: "FMSUBD"},   // +arg0-（arg1*arg2）
		{name: "FNMSUBS", argLength: 3, reg: fp31, asm: "FNMSUBS"}, // -arg0+（arg1*arg2）
		{name: "FNMSUBD", argLength: 3, reg: fp31, asm: "FNMSUBD"}, // -arg0+（arg1*arg2）
		{name: "MADD", argLength: 3, reg: gp31, asm: "MADD"},       // +arg0+（arg1*arg2）
		{name: "MADDW", argLength: 3, reg: gp31, asm: "MADDW"},     // +arg0+（arg1*arg2），32位
		{name: "MSUB", argLength: 3, reg: gp31, asm: "MSUB"},       // +arg0-（arg1*arg2）
		{name: "MSUBW", argLength: 3, reg: gp31, asm: "MSUBW"},     // +arg0-（arg1*arg2），32位

		// 转移
		{name: "SLL", argLength: 2, reg: gp21, asm: "LSL"},                        // arg0<<arg1，移位量为mod 64
		{name: "SLLconst", argLength: 1, reg: gp11, asm: "LSL", aux: "Int64"},     // arg0<<生长素，生长素应在0到63之间。
		{name: "SRL", argLength: 2, reg: gp21, asm: "LSR"},                        // arg0>>arg1，无符号，移位量为mod 64
		{name: "SRLconst", argLength: 1, reg: gp11, asm: "LSR", aux: "Int64"},     // arg0>>生长素，未签名，生长素应在0到63之间。
		{name: "SRA", argLength: 2, reg: gp21, asm: "ASR"},                        // arg0>>arg1，已签名，移位量为mod 64
		{name: "SRAconst", argLength: 1, reg: gp11, asm: "ASR", aux: "Int64"},     // arg0>>生长素，已签名，生长素应在0到63之间。
		{name: "ROR", argLength: 2, reg: gp21, asm: "ROR"},                        // arg0右转（arg1 mod 64）位
		{name: "RORW", argLength: 2, reg: gp21, asm: "RORW"},                      // arg0右旋转（arg1 mod 32）位
		{name: "RORconst", argLength: 1, reg: gp11, asm: "ROR", aux: "Int64"},     // arg0通过生长素位向右旋转，生长素应在0到63之间。
		{name: "RORWconst", argLength: 1, reg: gp11, asm: "RORW", aux: "Int64"},   // uint32（arg0）通过生长素位右转，生长素应在0到31的范围内。
		{name: "EXTRconst", argLength: 2, reg: gp21, asm: "EXTR", aux: "Int64"},   // 从arg0中提取64位：arg1从lsb auxInt开始，auxInt应该在0到63之间。
		{name: "EXTRWconst", argLength: 2, reg: gp21, asm: "EXTRW", aux: "Int64"}, // 从arg0[31:0]中提取32位：arg1[31:0]从lsb auxInt开始，顶部32位为零，auxInt应该在0到31之间。

		// 比较
		{name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"},                      // arg0与arg1进行比较
		{name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int64", typ: "Flags"},   // arg0与生长素的比较
		{name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"},                    // arg0与arg1比较，32位
		{name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", aux: "Int32", typ: "Flags"}, // arg0与生长素比较，32位
		{name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true},   // arg0与-arg1进行比较
		{name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int64", typ: "Flags"},   // arg0与生长素的比较
		{name: "CMNW", argLength: 2, reg: gp2flags, asm: "CMNW", typ: "Flags", commutative: true}, // arg0与-arg1比较，32位
		{name: "CMNWconst", argLength: 1, reg: gp1flags, asm: "CMNW", aux: "Int32", typ: "Flags"}, // arg0与-auxInt比较，32位
		{name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true},   // arg0&arg1与0比较
		{name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int64", typ: "Flags"},   // arg0&生长素与0比较
		{name: "TSTW", argLength: 2, reg: gp2flags, asm: "TSTW", typ: "Flags", commutative: true}, // arg0和arg1与0比较，32位
		{name: "TSTWconst", argLength: 1, reg: gp1flags, asm: "TSTW", aux: "Int32", typ: "Flags"}, // arg0&生长素与0比较，32位
		{name: "FCMPS", argLength: 2, reg: fp2flags, asm: "FCMPS", typ: "Flags"},                  // arg0与arg1比较，浮动32
		{name: "FCMPD", argLength: 2, reg: fp2flags, asm: "FCMPD", typ: "Flags"},                  // arg0与arg1比较，浮动64
		{name: "FCMPS0", argLength: 1, reg: fp1flags, asm: "FCMPS", typ: "Flags"},                 // arg0与0比较，浮动32
		{name: "FCMPD0", argLength: 1, reg: fp1flags, asm: "FCMPD", typ: "Flags"},                 // arg0与0比较，浮动64

		// 移位操作
		{name: "MVNshiftLL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"},                   // ^（arg0<<生长素），生长素应在0到63之间。
		{name: "MVNshiftRL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"},                   // ^（arg0>>生长素），无符号移位，生长素应该在0到63之间。
		{name: "MVNshiftRA", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"},                   // ^（arg0>>生长素），符号移位，生长素应该在0到63之间。
		{name: "NEGshiftLL", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"},                   // -（arg0<<生长素），生长素应在0到63之间。
		{name: "NEGshiftRL", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"},                   // -（arg0>>生长素），无符号移位，生长素应该在0到63之间。
		{name: "NEGshiftRA", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"},                   // -（arg0>>生长素），符号移位，生长素应该在0到63之间。
		{name: "ADDshiftLL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"},                   // arg0+arg1<<生长素，生长素应在0到63之间。
		{name: "ADDshiftRL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"},                   // arg0+arg1>>生长素，无符号移位，生长素应在0到63之间。
		{name: "ADDshiftRA", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"},                   // arg0+arg1>>生长素，符号移位，生长素应在0到63之间。
		{name: "SUBshiftLL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int64"},                   // arg0-arg1<<生长素，生长素应在0到63之间。
		{name: "SUBshiftRL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int64"},                   // arg0-arg1>>生长素，无符号移位，生长素应该在0到63之间。
		{name: "SUBshiftRA", argLength: 2, reg: gp21, asm: "SUB", aux: "Int64"},                   // arg0-arg1>>生长素，符号移位，生长素应在0到63之间。
		{name: "ANDshiftLL", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"},                   // arg0&（arg1<<生长素），生长素应在0到63之间。
		{name: "ANDshiftRL", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"},                   // 在auxInt>的范围内（arg0，arg0）应该是无符号的。
		{name: "ANDshiftRA", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"},                   // arg0&（arg1>>生长素），符号移位，生长素应在0到63之间。
		{name: "ORshiftLL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"},                    // arg0 | arg1<<生长素，生长素应在0到63之间。
		{name: "ORshiftRL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"},                    // arg0 | arg1>>生长素，无符号移位，生长素应在0到63之间。
		{name: "ORshiftRA", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"},                    // arg0 | arg1>>生长素，符号移位，生长素应在0到63之间。
		{name: "XORshiftLL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"},                   // arg0^arg1<<生长素，生长素应在0到63之间。
		{name: "XORshiftRL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"},                   // arg0^arg1>>生长素，无符号移位，生长素应在0到63之间。
		{name: "XORshiftRA", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"},                   // 要将^auxInt>置于arg0范围内，则应将^auxInt>置于arg0范围内。
		{name: "BICshiftLL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"},                   // arg0&^（arg1<生长素），生长素应在0到63之间。
		{name: "BICshiftRL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"},                   // arg0&^（arg1>>生长素），无符号移位，生长素应在0到63之间。
		{name: "BICshiftRA", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"},                   // arg0&^（arg1>>生长素），符号移位，生长素应在0到63之间。
		{name: "EONshiftLL", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"},                   // arg0^^（arg1<生长素），生长素应在0到63之间。
		{name: "EONshiftRL", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"},                   // arg0^^（arg1>>生长素），无符号移位，生长素应在0到63之间。
		{name: "EONshiftRA", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"},                   // arg0^^（arg1>>生长素），符号移位，生长素应在0到63之间。
		{name: "ORNshiftLL", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"},                   // arg0^（arg1<生长素），生长素应在0到63之间。
		{name: "ORNshiftRL", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"},                   // arg0^（arg1>>生长素），无符号移位，生长素应在0到63之间。
		{name: "ORNshiftRA", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"},                   // arg0^（arg1>>生长素），符号移位，生长素应在0到63之间。
		{name: "CMPshiftLL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0与arg1相比<<生长素，生长素应在0到63之间。
		{name: "CMPshiftRL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0与arg1比较>>生长素，无符号移位，生长素应在0到63之间。
		{name: "CMPshiftRA", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0与arg1相比>>生长素，符号移位，生长素应在0到63之间。
		{name: "CMNshiftLL", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // （arg0+arg1<<生长素）与0相比，生长素应在0到63之间。
		{name: "CMNshiftRL", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // （arg0+arg1>>生长素）与0相比，无符号移位，生长素应该在0到63之间。
		{name: "CMNshiftRA", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // （arg0+arg1>>生长素）与0相比，有符号移位，生长素应该在0到63之间。
		{name: "TSTshiftLL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // （arg0和arg1<<生长素）与0相比，生长素应在0到63之间。
		{name: "TSTshiftRL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // （arg0&arg1>>生长素）与0相比，无符号移位，生长素应该在0到63之间。
		{name: "TSTshiftRA", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // （arg0&arg1>>生长素）与0相比，有符号移位，生长素应该在0到63之间。

		// 位域运算
		// 对于所有位字段操作，lsb为auxInt>>8，宽度为auxInt&0xff
		// 将arg1的低宽度位插入从位lsb开始的结果中，从arg0复制其他位
		{name: "BFI", argLength: 2, reg: gp21nog, asm: "BFI", aux: "ARM64BitField", resultInArg0: true},
		// 从位lsb开始提取arg1的宽度位，并在结果的低端插入，从arg0复制其他位
		{name: "BFXIL", argLength: 2, reg: gp21nog, asm: "BFXIL", aux: "ARM64BitField", resultInArg0: true},
		// 将arg0的低宽度位从位lsb开始插入结果，插入位字段左侧的位设置为插入位字段的高位/符号位，右侧的位置零
		{name: "SBFIZ", argLength: 1, reg: gp11, asm: "SBFIZ", aux: "ARM64BitField"},
		// 从位lsb开始提取arg0的宽度位，并在结果的低端插入，剩余的高位设置为提取位字段的高位/符号位
		{name: "SBFX", argLength: 1, reg: gp11, asm: "SBFX", aux: "ARM64BitField"},
		// 将arg0的低宽度位从位lsb开始插入结果，插入位字段左侧和右侧的位置零
		{name: "UBFIZ", argLength: 1, reg: gp11, asm: "UBFIZ", aux: "ARM64BitField"},
		// 从位lsb开始提取arg0的宽度位，并在结果的低端插入，剩余的高位归零
		{name: "UBFX", argLength: 1, reg: gp11, asm: "UBFX", aux: "ARM64BitField"},

		// 移动
		{name: "MOVDconst", argLength: 0, reg: gp01, aux: "Int64", asm: "MOVD", typ: "UInt64", rematerializeable: true},      // 来自生长素的64位
		{name: "FMOVSconst", argLength: 0, reg: fp01, aux: "Float64", asm: "FMOVS", typ: "Float32", rematerializeable: true}, // 生长素为64位浮点，转换为32位浮点
		{name: "FMOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "FMOVD", typ: "Float64", rematerializeable: true}, // 生长素作为64位浮点

		{name: "MOVDaddr", argLength: 1, reg: regInfo{inputs: []regMask{buildReg("SP") | buildReg("SB")}, outputs: []regMask{gp}}, aux: "SymOff", asm: "MOVD", rematerializeable: true, symEffect: "Addr"}, // arg0+auxInt+aux（*gc.Sym），arg0=SP/SB

		{name: "MOVBload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVB", typ: "Int8", faultOnNilArg0: true, symEffect: "Read"},      // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVBUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVBU", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"},   // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVHload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVH", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"},     // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVHUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVHU", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"},  // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVWload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVW", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"},     // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVWUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVWU", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"},  // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVDload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVD", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"},    // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "FMOVSload", argLength: 2, reg: fpload, aux: "SymOff", asm: "FMOVS", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"}, // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "FMOVDload", argLength: 2, reg: fpload, aux: "SymOff", asm: "FMOVD", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"}, // 从arg0+auxInt+aux加载。arg1=mem。

		// 寄存器索引加载
		{name: "MOVDloadidx", argLength: 3, reg: gp2load, asm: "MOVD", typ: "UInt64"},    // 从arg0+arg1加载64位dword，arg2=mem。
		{name: "MOVWloadidx", argLength: 3, reg: gp2load, asm: "MOVW", typ: "Int32"},     // 从arg0+arg1加载32位字，符号扩展为64位，arg2=mem。
		{name: "MOVWUloadidx", argLength: 3, reg: gp2load, asm: "MOVWU", typ: "UInt32"},  // 从arg0+arg1加载32位字，零扩展到64位，arg2=mem。
		{name: "MOVHloadidx", argLength: 3, reg: gp2load, asm: "MOVH", typ: "Int16"},     // 从arg0+arg1加载16位字，符号扩展到64位，arg2=mem。
		{name: "MOVHUloadidx", argLength: 3, reg: gp2load, asm: "MOVHU", typ: "UInt16"},  // 从arg0+arg1加载16位字，零扩展到64位，arg2=mem。
		{name: "MOVBloadidx", argLength: 3, reg: gp2load, asm: "MOVB", typ: "Int8"},      // 从arg0+arg1加载8位字，符号扩展到64位，arg2=mem。
		{name: "MOVBUloadidx", argLength: 3, reg: gp2load, asm: "MOVBU", typ: "UInt8"},   // 从arg0+arg1加载8位字，零扩展到64位，arg2=mem。
		{name: "FMOVSloadidx", argLength: 3, reg: fp2load, asm: "FMOVS", typ: "Float32"}, // 从arg0+arg1加载32位浮点，arg2=mem。
		{name: "FMOVDloadidx", argLength: 3, reg: fp2load, asm: "FMOVD", typ: "Float64"}, // 从arg0+arg1、arg2=mem加载64位浮点。

		// 移位寄存器索引负载
		{name: "MOVHloadidx2", argLength: 3, reg: gp2load, asm: "MOVH", typ: "Int16"},     // 从arg0+arg1*2加载16位半字，符号扩展到64位，arg2=mem。
		{name: "MOVHUloadidx2", argLength: 3, reg: gp2load, asm: "MOVHU", typ: "UInt16"},  // 从arg0+arg1*2加载16位半字，零扩展到64位，arg2=mem。
		{name: "MOVWloadidx4", argLength: 3, reg: gp2load, asm: "MOVW", typ: "Int32"},     // 从arg0+arg1*4加载32位字，符号扩展为64位，arg2=mem。
		{name: "MOVWUloadidx4", argLength: 3, reg: gp2load, asm: "MOVWU", typ: "UInt32"},  // 从arg0+arg1*4加载32位字，零扩展到64位，arg2=mem。
		{name: "MOVDloadidx8", argLength: 3, reg: gp2load, asm: "MOVD", typ: "UInt64"},    // 从arg0+arg1*8加载64位双字，arg2=mem。
		{name: "FMOVSloadidx4", argLength: 3, reg: fp2load, asm: "FMOVS", typ: "Float32"}, // 从arg0+arg1*4加载32位浮点，arg2=mem。
		{name: "FMOVDloadidx8", argLength: 3, reg: fp2load, asm: "FMOVD", typ: "Float64"}, // 从arg0+arg1*8加载64位浮点，arg2=mem。

		{name: "MOVBstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},   // 将arg1的1字节存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVHstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},   // 将arg1的2个字节存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVWstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},   // 将arg1的4个字节存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVDstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},   // 将8字节的arg1存储到arg0+auxInt+aux。arg2=mem。
		{name: "STP", argLength: 4, reg: gpstore2, aux: "SymOff", asm: "STP", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},         // 将arg1和arg2的16字节存储到arg0+auxInt+aux。arg3=mem。
		{name: "FMOVSstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "FMOVS", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将arg1的4个字节存储到arg0+auxInt+aux。arg2=mem。
		{name: "FMOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "FMOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将8字节的arg1存储到arg0+auxInt+aux。arg2=mem。

		// 寄存器索引存储
		{name: "MOVBstoreidx", argLength: 4, reg: gpstore2, asm: "MOVB", typ: "Mem"},   // 将arg2的1字节存储到arg0+arg1，arg3=mem。
		{name: "MOVHstoreidx", argLength: 4, reg: gpstore2, asm: "MOVH", typ: "Mem"},   // 将arg2的2个字节存储到arg0+arg1，arg3=mem。
		{name: "MOVWstoreidx", argLength: 4, reg: gpstore2, asm: "MOVW", typ: "Mem"},   // 将arg2的4个字节存储到arg0+arg1，arg3=mem。
		{name: "MOVDstoreidx", argLength: 4, reg: gpstore2, asm: "MOVD", typ: "Mem"},   // 将8字节的arg2存储到arg0+arg1，arg3=mem。
		{name: "FMOVSstoreidx", argLength: 4, reg: fpstore2, asm: "FMOVS", typ: "Mem"}, // 将arg2的32位浮点存储到arg0+arg1，arg3=mem。
		{name: "FMOVDstoreidx", argLength: 4, reg: fpstore2, asm: "FMOVD", typ: "Mem"}, // 将arg2的64位浮点存储到arg0+arg1，arg3=mem。

		// 移位寄存器索引存储器
		{name: "MOVHstoreidx2", argLength: 4, reg: gpstore2, asm: "MOVH", typ: "Mem"},   // 将arg2的2个字节存储到arg0+arg1*2，arg3=mem。
		{name: "MOVWstoreidx4", argLength: 4, reg: gpstore2, asm: "MOVW", typ: "Mem"},   // 将arg2的4个字节存储到arg0+arg1*4，arg3=mem。
		{name: "MOVDstoreidx8", argLength: 4, reg: gpstore2, asm: "MOVD", typ: "Mem"},   // 将8字节的arg2存储到arg0+arg1*8，arg3=mem。
		{name: "FMOVSstoreidx4", argLength: 4, reg: fpstore2, asm: "FMOVS", typ: "Mem"}, // 将arg2的32位浮点存储到arg0+arg1*4，arg3=mem。
		{name: "FMOVDstoreidx8", argLength: 4, reg: fpstore2, asm: "FMOVD", typ: "Mem"}, // 将arg2的64位浮点存储到arg0+arg1*8，arg3=mem。

		{name: "MOVBstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将0的1字节存储到arg0+auxInt+aux。arg1=mem。
		{name: "MOVHstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将2个字节的零存储到arg0+auxInt+aux。arg1=mem。
		{name: "MOVWstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将4个字节的零存储到arg0+auxInt+aux。arg1=mem。
		{name: "MOVDstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将8个字节的零存储到arg0+auxInt+aux。arg1=mem。
		{name: "MOVQstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "STP", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},  // 将16个字节的零存储到arg0+auxInt+aux。arg1=mem。

		// 寄存器索引存储零
		{name: "MOVBstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVB", typ: "Mem"}, // 将0的1字节存储到arg0+arg1，arg2=mem。
		{name: "MOVHstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVH", typ: "Mem"}, // 将2个零字节存储到arg0+arg1，arg2=mem。
		{name: "MOVWstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVW", typ: "Mem"}, // 将4个零字节存储到arg0+arg1，arg2=mem。
		{name: "MOVDstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVD", typ: "Mem"}, // 将8个字节的零存储到arg0+arg1，arg2=mem。

		// 移位寄存器索引存储零
		{name: "MOVHstorezeroidx2", argLength: 3, reg: gpstore, asm: "MOVH", typ: "Mem"}, // 将2个零字节存储到arg0+arg1*2，arg2=mem。
		{name: "MOVWstorezeroidx4", argLength: 3, reg: gpstore, asm: "MOVW", typ: "Mem"}, // 将4个零字节存储到arg0+arg1*4，arg2=mem。
		{name: "MOVDstorezeroidx8", argLength: 3, reg: gpstore, asm: "MOVD", typ: "Mem"}, // 将8个零字节存储到arg0+arg1*8，arg2=mem。

		{name: "FMOVDgpfp", argLength: 1, reg: gpfp, asm: "FMOVD"}, // 将int64移动到float64（无转换）
		{name: "FMOVDfpgp", argLength: 1, reg: fpgp, asm: "FMOVD"}, // 将float64移动到int64（无转换）
		{name: "FMOVSgpfp", argLength: 1, reg: gpfp, asm: "FMOVS"}, // 将32位从int移到float reg（无转换）
		{name: "FMOVSfpgp", argLength: 1, reg: fpgp, asm: "FMOVS"}, // 将32位从浮点移到整数寄存器，零扩展（无转换）

		// 转换
		{name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVB"},   // 从arg0移动，从字节扩展符号
		{name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // 从arg0移动，从字节扩展为无符号
		{name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVH"},   // 从arg0开始移动，符号从一半延伸
		{name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // 从arg0开始移动，从一半开始无符号扩展
		{name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW"},   // 从arg0移动，从word扩展符号
		{name: "MOVWUreg", argLength: 1, reg: gp11, asm: "MOVWU"}, // 从arg0移动，从word扩展为无符号
		{name: "MOVDreg", argLength: 1, reg: gp11, asm: "MOVD"},   // 从arg0移动

		{name: "MOVDnop", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // 否，返回同一寄存器中的arg0

		{name: "SCVTFWS", argLength: 1, reg: gpfp, asm: "SCVTFWS"},   // int32->float32
		{name: "SCVTFWD", argLength: 1, reg: gpfp, asm: "SCVTFWD"},   // int32->float64
		{name: "UCVTFWS", argLength: 1, reg: gpfp, asm: "UCVTFWS"},   // uint32->float32
		{name: "UCVTFWD", argLength: 1, reg: gpfp, asm: "UCVTFWD"},   // uint32->float64
		{name: "SCVTFS", argLength: 1, reg: gpfp, asm: "SCVTFS"},     // int64->float32
		{name: "SCVTFD", argLength: 1, reg: gpfp, asm: "SCVTFD"},     // int64->float64
		{name: "UCVTFS", argLength: 1, reg: gpfp, asm: "UCVTFS"},     // uint64->float32
		{name: "UCVTFD", argLength: 1, reg: gpfp, asm: "UCVTFD"},     // uint64->float64
		{name: "FCVTZSSW", argLength: 1, reg: fpgp, asm: "FCVTZSSW"}, // float32->int32
		{name: "FCVTZSDW", argLength: 1, reg: fpgp, asm: "FCVTZSDW"}, // 浮点64->int32
		{name: "FCVTZUSW", argLength: 1, reg: fpgp, asm: "FCVTZUSW"}, // 浮动32->uint32
		{name: "FCVTZUDW", argLength: 1, reg: fpgp, asm: "FCVTZUDW"}, // 浮动64->uint32
		{name: "FCVTZSS", argLength: 1, reg: fpgp, asm: "FCVTZSS"},   // float32->int64
		{name: "FCVTZSD", argLength: 1, reg: fpgp, asm: "FCVTZSD"},   // 浮点64->int64
		{name: "FCVTZUS", argLength: 1, reg: fpgp, asm: "FCVTZUS"},   // 浮动32->uint64
		{name: "FCVTZUD", argLength: 1, reg: fpgp, asm: "FCVTZUD"},   // 浮动64->uint64
		{name: "FCVTSD", argLength: 1, reg: fp11, asm: "FCVTSD"},     // 浮动32->浮动64
		{name: "FCVTDS", argLength: 1, reg: fp11, asm: "FCVTDS"},     // 浮动64->浮动32

		// 浮点舍入到整数
		{name: "FRINTAD", argLength: 1, reg: fp11, asm: "FRINTAD"},
		{name: "FRINTMD", argLength: 1, reg: fp11, asm: "FRINTMD"},
		{name: "FRINTND", argLength: 1, reg: fp11, asm: "FRINTND"},
		{name: "FRINTPD", argLength: 1, reg: fp11, asm: "FRINTPD"},
		{name: "FRINTZD", argLength: 1, reg: fp11, asm: "FRINTZD"},

		// 条件指令；生长素是
		// 一种arm64比较伪操作（LessThan、LessThanU等）
		{name: "CSEL", argLength: 3, reg: gp2flags1, asm: "CSEL", aux: "CCop"},   // 生长素（旗）？arg0:arg1
		{name: "CSEL0", argLength: 2, reg: gp1flags1, asm: "CSEL", aux: "CCop"},  // 生长素（旗）？arg0:0
		{name: "CSINC", argLength: 3, reg: gp2flags1, asm: "CSINC", aux: "CCop"}, // 生长素（旗）？arg0:arg1+1
		{name: "CSINV", argLength: 3, reg: gp2flags1, asm: "CSINV", aux: "CCop"}, // 生长素（旗）？arg0:^arg1
		{name: "CSNEG", argLength: 3, reg: gp2flags1, asm: "CSNEG", aux: "CCop"}, // 生长素（旗）？arg0:-arg1
		{name: "CSETM", argLength: 1, reg: readflags, asm: "CSETM", aux: "CCop"}, // 生长素（旗）-1 : 0

		// 函数调用
		{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true},                                               // 调用静态函数aux。（*obj.LSym）。arg0=mem，auxint=argsize，返回mem
		{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // 通过闭包调用函数。arg0=codeptr，arg1=closure，arg2=mem，auxint=argsize，返回mem
		{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true},                         // 通过指针调用fn。arg0=codeptr，arg1=mem，auxint=argsize，返回mem

		// 伪操作
		{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // 如果arg0为零，则出现恐慌。arg1=mem。

		{name: "Equal", argLength: 1, reg: readflags},            // bool，true标志编码x==y，否则为false。
		{name: "NotEqual", argLength: 1, reg: readflags},         // 布尔，真标志编码x=否则我就错了。
		{name: "LessThan", argLength: 1, reg: readflags},         // bool，true标志编码有符号x<y，否则为false。
		{name: "LessEqual", argLength: 1, reg: readflags},        // bool，true标志编码有符号x<=y，否则为false。
		{name: "GreaterThan", argLength: 1, reg: readflags},      // bool，true标志编码有符号的x>y，否则为false。
		{name: "GreaterEqual", argLength: 1, reg: readflags},     // bool，true标志编码有符号x>=y，否则为false。
		{name: "LessThanU", argLength: 1, reg: readflags},        // bool，true标志编码无符号x<y，否则为false。
		{name: "LessEqualU", argLength: 1, reg: readflags},       // bool，true标志编码无符号x<=y，否则为false。
		{name: "GreaterThanU", argLength: 1, reg: readflags},     // bool，true标志编码无符号x>y，否则为false。
		{name: "GreaterEqualU", argLength: 1, reg: readflags},    // bool，true标志编码无符号x>=y，否则为false。
		{name: "LessThanF", argLength: 1, reg: readflags},        // bool，true标志编码浮点x<y，否则为false。
		{name: "LessEqualF", argLength: 1, reg: readflags},       // bool，true标志编码浮点x<=y，否则为false。
		{name: "GreaterThanF", argLength: 1, reg: readflags},     // bool，true标志编码浮点x>y，否则为false。
		{name: "GreaterEqualF", argLength: 1, reg: readflags},    // bool，true标志编码浮点x>=y，否则为false。
		{name: "NotLessThanF", argLength: 1, reg: readflags},     // bool，true标志编码浮点x>=y | | x与y无序，否则为false。
		{name: "NotLessEqualF", argLength: 1, reg: readflags},    // bool，true标志编码浮点x>y | | x与y无序，否则为false。
		{name: "NotGreaterThanF", argLength: 1, reg: readflags},  // bool，true标志编码浮点x<=y | | x与y无序，否则为false。
		{name: "NotGreaterEqualF", argLength: 1, reg: readflags}, // bool，true标志编码浮点x<y | | x与y无序，否则为false。
		// 达夫零
		// arg0=内存地址为零
		// arg1=mem
		// auxint=偏移到duffzero代码中以开始执行
		// 返回mem
		// R20改变为副作用
		// R16和R17可能会被连接器蹦床撞击。
		{
			name:      "DUFFZERO",
			aux:       "Int64",
			argLength: 2,
			reg: regInfo{
				inputs:   []regMask{buildReg("R20")},
				clobbers: buildReg("R16 R17 R20 R30"),
			},
			faultOnNilArg0: true,
			unsafePoint:    true, // 达夫零点附近的FP维护可能会因中断而中断
		},

		// 大零点
		// arg0=内存地址为零（在R16又称arm64.REGT1中，更改为副作用）
		// arg1=最后一个16字节单元的地址为零
		// arg2=mem
		// 返回mem
		// STP.P（锆，锆），16（R16）
		// CMP-Rarg1，R16
		// BLE-2（个人电脑）
		// 注意：内存的结尾可能不是有效的指针。如果洒了，那就是个问题。
		// 内存-16的末尾区域为零，可以溢出。
		{
			name:      "LoweredZero",
			argLength: 3,
			reg: regInfo{
				inputs:   []regMask{buildReg("R16"), gp},
				clobbers: buildReg("R16"),
			},
			clobberFlags:   true,
			faultOnNilArg0: true,
		},

		// 复印件
		// arg0=dst内存地址（在R21中，因副作用而更改）
		// arg1=src内存地址（在R20中，作为副作用更改）
		// arg2=mem
		// auxint=要开始执行的duffcopy代码的偏移量
		// 返回mem
		// R20、R21因副作用而改变
		// R16和R17可能会被连接器蹦床撞击。
		{
			name:      "DUFFCOPY",
			aux:       "Int64",
			argLength: 3,
			reg: regInfo{
				inputs:   []regMask{buildReg("R21"), buildReg("R20")},
				clobbers: buildReg("R16 R17 R20 R21 R26 R30"),
			},
			faultOnNilArg0: true,
			faultOnNilArg1: true,
			unsafePoint:    true, // DUFFCOPY周围的FP维护可能会因中断而中断
		},

		// 大动作
		// arg0=dst内存的地址（在R17又称arm64.2中，由于副作用而更改）
		// arg1=src内存的地址（在R16又称arm64.REGT1中，由于副作用而更改）
		// arg2=src最后一个元素的地址
		// arg3=mem
		// 返回mem
		// 第8节（R16），Rtmp
		// 移动P Rtmp，8（R17）
		// CMP-Rarg2，R16
		// BLE-3（个人电脑）
		// 注意：src的结尾可能不是有效的指针。如果洒了，那就是个问题。
		// src-8的末端在要复制的区域内，可以溢出。
		{
			name:      "LoweredMove",
			argLength: 4,
			reg: regInfo{
				inputs:   []regMask{buildReg("R17"), buildReg("R16"), gp},
				clobbers: buildReg("R16 R17"),
			},
			clobberFlags:   true,
			faultOnNilArg0: true,
			faultOnNilArg1: true,
		},

		// 调度器确保LoweredGetClosurePtr仅在入口块中发生，
		// 并将其排序到块的最开始，以防止其他
		// R26（arm64.REGCTXT，闭包指针）的使用
		{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R26")}}, zeroWidth: true},

		// LoweredGetCallerSP返回当前函数调用方的SP。
		{name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},

		// LoweredGetCallerPC计算其“调用者”将返回的PC。
		// 也就是说，如果f调用g“calls”getcallerpc，
		// 结果应为g将返回到的f内的PC。
		// 有关更详细的讨论，请参阅runtime/stubs.go。
		{name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},

		// 常量标志值。
		// 注意：浮点运算有一个“无序”结果
		// 比较，但我们还没有使用这样的野兽。
		// 此op供重写规则临时使用。信息技术
		// 无法显示在生成的程序集中。
		{name: "FlagConstant", aux: "FlagConstant"},

		// None
		// InvertFlags是一个伪操作，不能出现在程序集输出中。
		{name: "InvertFlags", argLength: 1}, // arg0的反向

		// 原子负荷。
		// 从arg0加载。arg1=mem。生长素必须为零。
		// 返回<value，memory>，以便可以与其他加载一起正确排序。
		{name: "LDAR", argLength: 2, reg: gpload, asm: "LDAR", faultOnNilArg0: true},
		{name: "LDARB", argLength: 2, reg: gpload, asm: "LDARB", faultOnNilArg0: true},
		{name: "LDARW", argLength: 2, reg: gpload, asm: "LDARW", faultOnNilArg0: true},

		// 原子仓库。
		// 将arg1存储到arg0。arg2=mem。返回内存。生长素必须为零。
		{name: "STLRB", argLength: 3, reg: gpstore, asm: "STLRB", faultOnNilArg0: true, hasSideEffects: true},
		{name: "STLR", argLength: 3, reg: gpstore, asm: "STLR", faultOnNilArg0: true, hasSideEffects: true},
		{name: "STLRW", argLength: 3, reg: gpstore, asm: "STLRW", faultOnNilArg0: true, hasSideEffects: true},

		// 原子交换。
		// 将arg1存储到arg0。arg2=mem。返回<old content of*arg0，memory>。生长素必须为零。
		// LDAXR（Rarg0），路由
		// STLXR Rarg1，（Rarg0），Rtmp
		// CBNZ Rtmp，-2（PC）
		{name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// 原子交换变体。
		// 将arg1存储到arg0。arg2=mem。返回<old content of*arg0，memory>。生长素必须为零。
		// SWPALD Rarg1，（Rarg0），路由
		{name: "LoweredAtomicExchange64Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
		{name: "LoweredAtomicExchange32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},

		// 原子加法。
		// *arg0+=arg1。arg2=mem。返回<新的*arg0内容，内存>。生长素必须为零。
		// LDAXR（Rarg0），路由
		// 添加Rarg1，Rout
		// STLXR路由（Rarg0），Rtmp
		// CBNZ Rtmp，-3（PC）
		{name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// 原子添加变量。
		// *arg0+=arg1。arg2=mem。返回<新的*arg0内容，内存>。生长素必须为零。
		// LDADDAL（Rarg0），Rarg1，路由器
		// 添加Rarg1，Rout
		{name: "LoweredAtomicAdd64Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
		{name: "LoweredAtomicAdd32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},

		// 原子比较和交换。
		// arg0=指针，arg1=旧值，arg2=新值，arg3=内存。生长素必须为零。
		// 如果*arg0==arg1{
		// *arg0=arg2
		// 返回（真，内存）
		// }否则{
		// 返回（假，内存）
		// }
		// LDAXR（Rarg0），Rtmp
		// CMP Rarg1，Rtmp
		// BNE 3（个人电脑）
		// STLXR Rarg2，（Rarg0），Rtmp
		// CBNZ Rtmp，-4（件）
		// CSET均衡，路由
		{name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// 原子比较和交换变体。
		// arg0=指针，arg1=旧值，arg2=新值，arg3=内存。生长素必须为零。
		// 如果*arg0==arg1{
		// *arg0=arg2
		// 返回（真，内存）
		// }否则{
		// 返回（假，内存）
		// }
		// MOV Rarg1，Rtmp
		// CASAL Rtmp（Rarg0），Rarg2
		// CMP Rarg1，Rtmp
		// CSET均衡，路由
		{name: "LoweredAtomicCas64Variant", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicCas32Variant", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// 原子和/或。
		// *arg0&=（|=）arg1。arg2=mem。返回<新的*arg0内容，内存>。生长素必须为零。
		// LDAXR（Rarg0），路由
		// 和/或Rarg1，溃败
		// STLXR路由（Rarg0），Rtmp
		// CBNZ Rtmp，-3（PC）
		{name: "LoweredAtomicAnd8", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "AND", typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicAnd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "AND", typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicOr8", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "ORR", typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicOr32", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "ORR", typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// 原子和/或变体。
		// *arg0&=（|=）arg1。arg2=mem。返回<新的*arg0内容，内存>。生长素必须为零。
		// 以及：
		// MNV Rarg1，Rtemp
		// LDANDALB Rtemp（Rarg0），路由
		// 还有Rarg1，溃败
		// 或：
		// LDORALB Rarg1，（Rarg0），路由
		// 奥尔·拉格，溃败
		{name: "LoweredAtomicAnd8Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicAnd32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicOr8Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true},
		{name: "LoweredAtomicOr32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true},

		// LoweredWB调用runtime.gcWriteBarrier。arg0=destptr，arg1=srcptr，arg2=mem，aux=runtime.gcWriteBarrier
		// 如有必要，它会保存所有GP寄存器，
		// 但击倒R30（LR），因为这是一个电话。
		// R16和R17可能会被连接器蹦床撞击。
		{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R16 R17 R30")}, clobberFlags: true, aux: "Sym", symEffect: "None"},

		// 这些函数有三个，因此它们可以有三个不同的寄存器输入。
		// 当我们检查0<=c<=cap（A），然后检查0<=b<=c（b），然后检查0<=A<=b（c），我们需要
		// 要匹配的默认寄存器，因此我们不需要不必要地复制寄存器。
		{name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见generic.go中的PanicBounds）。
		{name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见generic.go中的PanicBounds）。
		{name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r0, r1}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见generic.go中的PanicBounds）。
	}

	blocks := []blockData{
		{name: "EQ", controls: 1},
		{name: "NE", controls: 1},
		{name: "LT", controls: 1},
		{name: "LE", controls: 1},
		{name: "GT", controls: 1},
		{name: "GE", controls: 1},
		{name: "ULT", controls: 1},
		{name: "ULE", controls: 1},
		{name: "UGT", controls: 1},
		{name: "UGE", controls: 1},
		{name: "Z", controls: 1},                  // 控件==0（采用寄存器而不是标志）
		{name: "NZ", controls: 1},                 // 控制！=0
		{name: "ZW", controls: 1},                 // 控件==0，32位
		{name: "NZW", controls: 1},                // 控制！=0，32位
		{name: "TBZ", controls: 1, aux: "Int64"},  // 对照组和（1<<生长素）==0
		{name: "TBNZ", controls: 1, aux: "Int64"}, // 对照组和（1<<生长素）！=0
		{name: "FLT", controls: 1},
		{name: "FLE", controls: 1},
		{name: "FGT", controls: 1},
		{name: "FGE", controls: 1},
		{name: "LTnoov", controls: 1}, // “它”但不尊重溢出
		{name: "LEnoov", controls: 1}, // “乐”，但不尊重溢出
		{name: "GTnoov", controls: 1}, // “GT”但不尊重溢出
		{name: "GEnoov", controls: 1}, // “GE”但不尊重溢出
	}

	archs = append(archs, arch{
		name:            "ARM64",
		pkg:             "cmd/internal/obj/arm64",
		genfile:         "../../arm64/ssa.go",
		ops:             ops,
		blocks:          blocks,
		regnames:        regNamesARM64,
		gpregmask:       gp,
		fpregmask:       fp,
		framepointerreg: -1, // 不用
		linkreg:         int8(num["R30"]),
	})
}
